#pragma once 
#include<iostream>
#include<pthread.h>
#include<queue>
#include"Tack.hpp"
#include"Log.hpp"

#define NUM 6

class ThreadPool{
  
  private:
    bool stop;
    int num;
    std::queue<Tack> q;
    pthread_mutex_t lock;
    pthread_cond_t cond;
    
    ThreadPool(int _num=NUM):num(_num),stop(false)
    {
      Init();
    }
    ThreadPool(const ThreadPool&)
    {}
    ~ThreadPool()
    {
      pthread_mutex_destroy(&lock);
      pthread_cond_destroy(&cond);
    }
    static pthread_mutex_t _mute;
    static ThreadPool* th;
  public:

    static ThreadPool* GetThread()
    {
      if(th==nullptr){
        pthread_mutex_lock(&_mute);
        if(th==nullptr){
          th=new ThreadPool();
          th->InitThread();
        }
        pthread_mutex_unlock(&_mute);
      }
      return th;
    }
    void Init()
    {
      pthread_mutex_init(&lock,nullptr);
      pthread_cond_init(&cond,nullptr);
    }
    void Lock()
    {
      pthread_mutex_lock(&lock);
    }
    void UnLock()
    {
      pthread_mutex_unlock(&lock);
    }
    void CondWait()
    {
      pthread_cond_wait(&cond,&lock);
    }
    void CondUp()
    {
      pthread_cond_signal(&cond);
    }
    bool IsQueueEmpty()
    {
      return q.size()==0?true:false;
    }
    static void* Handler(void* arg)
    {
      ThreadPool* p=(ThreadPool*)arg;

      while(true){
        Tack t;
        p->Lock();
        while(p->IsQueueEmpty()){
          p->CondWait();
        }
        p->PopTack(t);
        p->UnLock();
        t.RequsetOn();
      }
    }
    bool InitThread()
    {
      pthread_t pid;
      for(int i=0;i<num;i++){
        std::cout<<"----------"<<std::endl;
        if(pthread_create(&pid,nullptr,Handler,this)!=0){
          LOG(ERROR,"pthread create error");
          return false;
        }
      }
      LOG(INFO,"pthread create success");
      return true;
    }
    void PushTack(Tack in)
    {
      Lock();
      q.push(in);
      UnLock();
      CondUp();
    }
    void PopTack(Tack &ou)
    {
      ou=q.front();
      q.pop();
    }
};
ThreadPool* ThreadPool::th=nullptr;
pthread_mutex_t ThreadPool::_mute=PTHREAD_MUTEX_INITIALIZER;

